package com.fsnbigdata.web;
import com.fsnbigdata.domain.Document;
import com.fsnbigdata.domain.Organism;
import com.fsnbigdata.enums.ResultEnum;
import com.fsnbigdata.exception.ParamException;
import com.fsnbigdata.service.api.DocumentService;
import com.fsnbigdata.util.ReflectUtil;
import io.swagger.annotations.*;

import java.lang.reflect.Method;
import java.security.Principal;
import org.springframework.roo.addon.web.mvc.controller.annotations.ControllerType;
import org.springframework.roo.addon.web.mvc.controller.annotations.RooController;
import org.springframework.roo.addon.web.mvc.controller.annotations.responses.json.RooJSON;
import com.fsnbigdata.service.api.OrganismService;
import io.springlets.web.NotFoundException;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import org.springframework.web.util.UriComponents;
import springfox.documentation.annotations.ApiIgnore;

import java.util.Set;
import java.util.stream.Collectors;

/**
 * = OrganismsItemJsonController
 *
 * TODO Auto-generated class documentation
 *
 */
@RooController(entity = Organism.class, pathPrefix = "/api", type = ControllerType.ITEM)
@RooJSON
@RestController
@RequestMapping(value = "/api/organisms/{id}", name = "OrganismsItemJsonController", produces = MediaType.APPLICATION_JSON_VALUE)
@Api(tags = "Organism", description = "生物" )
public class OrganismsItemJsonController {

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    private OrganismService organismService;

    private DocumentService documentService;

    /**
     * TODO Auto-generated constructor documentation
     *
     * @param organismService
     */
    @Autowired
    public OrganismsItemJsonController(OrganismService organismService, DocumentService documentService) {
        this.organismService = organismService;
        this.documentService = documentService;
    }

    /**
     * TODO Auto-generated method documentation
     *
             * @return OrganismService
     */
    public OrganismService getOrganismService() {
        return organismService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param organismService
     */
    public void setOrganismService(OrganismService organismService) {
        this.organismService = organismService;
    }

    public DocumentService getDocumentService() {
        return documentService;
    }

    public void setDocumentService(DocumentService documentService) {
        this.documentService = documentService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param id
     * @return Organism
     */
    @ModelAttribute
    public Organism getOrganism(@PathVariable("id") Long id) {
        Organism organism = organismService.findOne(id);
        if (organism == null) {
            throw new NotFoundException(String.format("Organism with identifier '%s' not found", id));
        }
        return organism;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param organism
     * @return ResponseEntity
     */
    @GetMapping(name = "show")
    @ApiResponses({
            @ApiResponse(code = 200, message = "", response = Organism.class)
    })
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "", paramType = "path", dataType = "int", required = true)
    })
    //@PreAuthorize("hasRole('USER')")
    public ResponseEntity<?> show(@ApiIgnore @ModelAttribute Organism organism) {
        return ResponseEntity.ok(organism);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param organism
     * @return UriComponents
     */
    public static UriComponents showURI(Organism organism) {
        return MvcUriComponentsBuilder.fromMethodCall(MvcUriComponentsBuilder.on(OrganismsItemJsonController.class).show(organism)).buildAndExpand(organism.getId()).encode();
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param storedOrganism
     * @param organism
     * @param result
     * @return ResponseEntity
     */
    @PutMapping(name = "update")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "", paramType = "path", dataType = "int", required = true)
    })
    @PreAuthorize("hasRole('DB_ORGANISM')")
    @ApiOperation(value = "",notes = "update")
    public ResponseEntity<?> update(
        @ApiIgnore @ModelAttribute Organism storedOrganism,
        @Valid @RequestBody Organism organism,
        BindingResult result,
        Principal principal) throws Exception {
        if (result.hasErrors()) {
            throw new ParamException(ResultEnum.PARAM_ERROR.getCode(),
                    result.getFieldError().getDefaultMessage());
        }
        organism.setId(storedOrganism.getId());

        Set<Document> toSaveDocs = organism.getDocs();
        organism.setDocs(storedOrganism.getDocs());

        String name =  getOrganismService().findOne(storedOrganism.getId()).getName();
        Organism retval = getOrganismService().save(organism);

        Set<Long> docIds = toSaveDocs.stream().map(doc -> {
            if(doc.getId() == null) {
                doc.setCreator(principal.getName());
                getDocumentService().save(doc);
                return doc.getId();
            }else{
                return doc.getId();
            }
        }).collect(Collectors.toSet());

        getOrganismService().setDocs(retval, docIds);

        Class<?> clazz = OrganismsItemJsonController.class;
        Method method = clazz.getMethod("update", ReflectUtil.getPeremeterClass(clazz, "update"));
        ReflectUtil.setAnnotationOn(method,"更新物种库，名称："+name);
        return ResponseEntity.ok(retval);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param organism
     * @return ResponseEntity
     */
    @DeleteMapping(name = "delete")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "", paramType = "path", dataType = "int", required = true)
    })
    @PreAuthorize("hasRole('DB_ORGANISM')")
    @ApiOperation(value = "",notes = "delete")
    public ResponseEntity<?> delete(@ApiIgnore @ModelAttribute Organism organism) throws Exception {
        getOrganismService().delete(organism);
        Class<?> clazz = OrganismsItemJsonController.class;
        Method method = clazz.getMethod("delete", ReflectUtil.getPeremeterClass(clazz, "delete"));
        ReflectUtil.setAnnotationOn(method,"删除物种库，中文名："+organism.getName());
        return ResponseEntity.ok().build();
    }
}
